package com.cancer.common.util;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.UndeclaredThrowableException;

public final class ExceptionUtil {
	private ExceptionUtil() {
	}

	/**
	 * 输出异常堆栈
	 * 
	 * @author 刘俊 2016年7月19日
	 * @param thr
	 * @return
	 */
	public static String getStackTrace(Throwable thr) {
		StringWriter sw = new StringWriter();

		try (PrintWriter pw = new PrintWriter(sw)) {
			thr.printStackTrace(pw);
		}
		
		return sw.toString();
	}
	/**
     * 获得完整消息，包括异常名
     * 
     * @param e 异常
     * @return 完整消息
     */
    public static String getMessage(Throwable e) {
        return String.format("%s: %s", e.getClass().getSimpleName(), e.getMessage());
    }
    
    /**
     * 使用运行时异常包装编译异常
     * @param throwable 异常
     * @return 运行时异常
     */
    public static RuntimeException wrapRuntime(Throwable throwable){
        if(throwable instanceof RuntimeException){
            return (RuntimeException) throwable;
        }else{
            return new RuntimeException(throwable);
        }
    }

    /**
     * 剥离反射引发的InvocationTargetException、UndeclaredThrowableException中间异常，返回业务本身的异常
     * @param wrapped 包装的异常
     * @return 剥离后的异常
     */
    public static Throwable unwrap(Throwable wrapped) {
        Throwable unwrapped = wrapped;
        while (true) {
            if (unwrapped instanceof InvocationTargetException) {
                unwrapped = ((InvocationTargetException) unwrapped).getTargetException();
            } else if (unwrapped instanceof UndeclaredThrowableException) {
                unwrapped = ((UndeclaredThrowableException) unwrapped).getUndeclaredThrowable();
            } else {
                return unwrapped;
            }
        }
    }
    
    /**
     * 获取当前栈信息
     * 
     * @return 当前栈信息
     */
    public static StackTraceElement[] getStackElements() {
        return (new Throwable()).getStackTrace();
    }
}
